/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = sybase_request.c                                              */
/*  NOTE      = TDS协议解析                                                   */
/*  DATE      = 2014/05/27 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>

#include "sybase_core.h"
#include "sybase_common.h"
#include "sybase_token.h"

/*******************************************************************************
*  FUNC     :  判定是否需要生成request
*  ARGS     :  p_st_private (私有数据)
*           :  u8_request_type (request类型)
*  RTN      :  APM_L7_ANALYZE_SUCC
*              APM_L7_ANALYZE_FAIL
*  NOTE     :  p_st_private肯定不为NULL
*******************************************************************************/
static int __sybase_chk_request(L7session_sybase_private *p_st_private
                                , uint8_t u8_packet_type)
{
    L7_req_sybase *p_st_req = NULL;
    /*
    * 上次解析的packet已经是一个完整的request了,
    * 但由于接收response或者解析的原因,没有解析到相应的response,
    * 这时需要将上一次的request信息释放掉
    */
    if (p_st_private->p_st_req
        && p_st_private->p_st_req->i_need_req_resp == FRTDS_DIRECT_RESPONSE)
    {
        /* 销毁上次的request信息 */
        sybase_destroy_request(&(p_st_private->p_st_req));
    }

    /* 需要创建request */
    if (p_st_private->p_st_req == NULL)
    {
        p_st_req = sybase_create_request(u8_packet_type);
        /* 创建失败 */
        if (p_st_req == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        p_st_private->p_st_req = p_st_req;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  将packet添加到对应的statement
*  ARGS     :  p_st_private (私有信息)
*           :  i_cursor_dynamic (cursor or dynamic)
*  RTN      :  APM_L7_ANALYZE_SUCC
*              APM_L7_ANALYZE_FAIL
*  NOTE     :  p_st_private肯定不为NULL
*******************************************************************************/
static int __sybase_get_statement(L7session_sybase_private *p_st_private
                                  , int i_cursor_dynamic)
{
    Frlist_node *p_hash_node = NULL;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    L7_req_sybase *p_st_req = p_st_private->p_st_req;

    /* 处理cursor信息 */
    if (i_cursor_dynamic == SYBASE_CURSOR)
    {
        /* find statement for hash */
        if (p_st_req->l_cursor_id)
        {
            p_hash_node = frhash2_getLong(p_st_private->p_hash_prepare
                                         , p_st_req->l_cursor_id);
        }
        else
        {
            p_hash_node = frhash2_getStr(p_st_private->p_hash_prepare
                                        , p_st_req->arr_cursor_name
                                        , strlen(p_st_req->arr_cursor_name));
        }
    }
    else /* 处理dynamic */
    {
        p_hash_node = frhash2_getStr(p_st_private->p_hash_prepare
                                    , p_st_req->arr_id
                                    , strlen(p_st_req->arr_id));
    }

    /* 取得statement */
    p_st_statement = (Sql_statement *)FRLIST_GET_NODE_DATA(p_hash_node);
    if (p_st_statement == NULL)
    {
        frdbg("Get statement from hash failed");
        return APM_L7_ANALYZE_FAIL;
    }
    p_st_resultset = frdb_get_last_resultset(p_st_statement);

    /* 出力设置 */
    p_st_req->i_new_statement = FR_NO;
    p_st_req->p_st_statement = p_st_statement;
    p_st_req->p_st_resultset = p_st_resultset;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  创建statement
*  ARGS     :  p_st_private (私有信息)
*           :  i_cursor_dynamic (cursor or dynamic)
*  RTN      :  APM_L7_ANALYZE_SUCC
*              APM_L7_ANALYZE_FAIL
*  NOTE     :  p_st_private肯定不为NULL
*******************************************************************************/
static int __sybase_create_statement(Conntrack *p_st_conn
                                     , L7session_sybase_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    unsigned long ul_req_sequence = 0;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    L7_req_sybase *p_st_req = p_st_private->p_st_req;

    /* 如果一个packet里出现了两个sql statement当做错误处理 */
    if (p_st_req->p_st_statement)
    {
        frdbg("There are double sql statemet in one packet!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* create statement */
    p_st_statement = frdb_create_statement();
    if (p_st_statement == NULL)
    {
        frdbg("Call frdb_create_statement failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    /* 设置sql statement */
    frdb_set_sql(p_st_statement, p_st_req->p_sql);
    p_st_req->p_sql = NULL;

    /* 创建结果集 */
    ul_req_sequence = frct_seq_increase(p_st_conn);
    p_st_resultset = frdb_create_resultset(ul_req_sequence);
    if (p_st_resultset == NULL)
    {
        frdbg("Create sqlbatch resultset failed!\n");
        frdb_statement_free(&p_st_statement);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 追加结果集到statement */
    i_ret = frdb_add_resultset(p_st_statement, p_st_resultset);
    if (i_ret != FR_SUCC)
    {
        frdbg("Insert resultset into statement failed!\n");
        frdb_statement_free(&p_st_statement);
        frdb_resultset_free(&p_st_resultset);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 出力设置 */
    p_st_req->i_new_statement = FR_YES;
    p_st_req->p_st_statement = p_st_statement;
    p_st_req->p_st_resultset = p_st_resultset;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析LOGIN
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*           :  p_st_hash_report(保存Frreport_data)
*           :  i_cancel_flg(当前packet的取消flag)
*           :  i_whole_flg(packert完整flag)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int sybase_parse_buf_login(Conntrack *p_st_conn
                          , L7session_sybase_private *p_st_private
                          , Frhash_header *p_st_hash_report
                          , int i_cancel_flg
                          , int i_whole_flg)
{
    uint8_t u8_token_type = 0;
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_req_sybase *p_st_req = NULL;
    L7session_sybase *p_st_session = p_st_private->p_st_sess;
    L7_fragment_sybase *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 判断创建request */
    i_ret = __sybase_chk_request(p_st_private, TDS50_MSGTYPE_BUF_LOGIN);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("__sybase_chk_request failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    p_st_req = p_st_private->p_st_req;

    /* LOGIN message */
    if (p_st_req->i_login_status == FRTDS_LOGIN_START)
    {
        /* LOGIN 没有长数据, 接收完了之后再统一解析 */
        if (i_whole_flg == FR_NO)
        {
            return APM_L7_ANALYZE_TODO;
        }
        p_st_req->i_req_type = TDS50_MSGTYPE_BUF_LOGIN;

        /* 解析login信息 */
        i_ret = sybase_parse_login_token(p_st_data, i_whole_flg, p_st_session);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("LOGIN parse Failed\n");
            return APM_L7_ANALYZE_FAIL;
        }

        /* 查看是否还有剩余数据,有的话只能是TOKEN_CAPABILITY */
        if (bytebuff_remaining(p_st_data))
        {
            bytebuff_get_char(p_st_data, &u8_token_type);
            if (u8_token_type == TDS50_TOKEN_CAPABILITY)
            {
                i_ret = sybase_parse_capability_token(p_st_data, i_whole_flg
                                                     ,FRTDS_DIRECT_REQUEST
                                                     , p_st_session);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("Capability parse Failed\n");
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            else
            {
                frdbg("There has another token in login message!\n");
                return APM_L7_ANALYZE_FAIL;
            }
        }

        i_ret = APM_L7_ANALYZE_SET_LOGIN(APM_L7_ANALYZE_SUCC);
        return APM_L7_ANALYZE_SET_REQ(i_ret);
    }
    /* LOGIN message之后还有MSG */
    else if (p_st_req->i_login_status == FRTDS_LOGIN_NEGOTIATE)
    {
        /* 现不对MSG做解析,因为session信息不计算时间长度，只需要跳过即可 */
        if (i_whole_flg == FR_NO)
        {
            return APM_L7_ANALYZE_TODO;
        }
        else
        {
            return APM_L7_ANALYZE_SUCC;
        }
    }
    else
    {
        return APM_L7_ANALYZE_FAIL;
    }
}

/*******************************************************************************
*  FUNC     :  解析Language
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*           :  p_st_hash_report(保存Frreport_data)
*           :  i_cancel_flg(当前packet的取消flag)
*           :  i_whole_flg(packert完整flag)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int sybase_parse_buf_lang(Conntrack *p_st_conn
                         , L7session_sybase_private *p_st_private
                         , Frhash_header *p_st_hash_report
                         , int i_cancel_flg
                         , int i_whole_flg)
{
    /* 没有长数据,所以整个packet完了再取 */
    if (i_whole_flg == FR_NO)
    {
        return APM_L7_ANALYZE_TODO;
    }

    int i_ret = FR_SUCC;
    unsigned int ui_len = 0;
    unsigned int ul_req_sequence = 0;
    char *p_sql = NULL;
    L7_req_sybase *p_st_req = NULL;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    Frreport_body_data *p_st_report_body = NULL;
    L7_fragment_sybase *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 判断创建request */
    i_ret = __sybase_chk_request(p_st_private, TDS50_MSGTYPE_BUF_LANG);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("__sybase_chk_request failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    p_st_req = p_st_private->p_st_req;

    /* 取得sql */
    ui_len = bytebuff_remaining(p_st_data);
    p_sql = (char *)frmalloc(ui_len + 1);
    if (p_sql == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_sql, ui_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_sql);
        return APM_L7_ANALYZE_FAIL;
    }
    p_sql[ui_len] = '\0';

    /* 创建statement */
    p_st_statement = frdb_create_statement();
    if (p_st_statement == NULL)
    {
        frfree(p_sql);
        frdbg("Call frdb_create_statement failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    /* 设置sql statement */
    frdb_set_sql(p_st_statement, p_sql);

    /* 创建结果集 */
    ul_req_sequence = frct_seq_increase(p_st_conn);
    p_st_resultset = frdb_create_resultset(ul_req_sequence);
    if (p_st_resultset == NULL)
    {
        frdbg("Create sqlbatch resultset failed!\n");
        frdb_statement_free(&p_st_statement);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 追加结果集到statement */
    i_ret = frdb_add_resultset(p_st_statement, p_st_resultset);
    if (i_ret != FR_SUCC)
    {
        frdbg("Insert resultset into statement failed!\n");
        frdb_statement_free(&p_st_statement);
        frdb_resultset_free(&p_st_resultset);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置结果集信息 */
    frdb_set_resultset_req2(p_st_resultset
                           , p_st_fragment->ui_total_len
                           , &(p_st_fragment->st_first_timestamp)
                           , &(p_st_fragment->st_end_timestamp));

    /* 设置request索引 */
    p_st_req->p_st_statement = p_st_statement;
    p_st_req->p_st_resultset = p_st_resultset;

    /* 创建report body */
    p_st_report_body = sybase_new_report_body(p_st_conn, p_st_private->p_st_sess);
    /* 创建report body失败时，不释放做成的request */
    if (p_st_report_body == NULL)
    {
        frdbg("sybase_new_report_body failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 上报request数据 */
    i_ret = frdb_report_req2(p_st_conn, p_st_hash_report, p_st_statement
                             , p_st_resultset, &p_st_report_body);
    /* 上报request数据失败时，不释放做成的request */
    if (i_ret != FR_SUCC)
    {
        frdbg("frdb_report_req2 failed!\n");
        frreport_body_free(&p_st_report_body);
        return APM_L7_ANALYZE_SUCC;
    }

    //frdbg("Parse Language success!\n");
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  解析TOKENIZED TDS REQUEST
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*           :  p_st_hash_report(保存Frreport_data)
*           :  i_req_resp(请求/响应)
*           :  i_cancel_flg(当前packet的取消flag)
*           :  i_whole_flg(packert完整flag)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int sybase_parse_normal(Conntrack *p_st_conn
                       , L7session_sybase_private *p_st_private
                       , Frhash_header *p_st_hash_report
                       , int i_cancel_flg
                       , int i_whole_flg)
{
    uint8_t u8_token_type = 0;
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_options = 0;
    int i_dynamic_type = 0;
    int i_angin_flg = FR_NO;
    Frlist_node *p_st_node = NULL;
    L7_req_sybase *p_st_req = NULL;
    Sql_field_bind *p_lst_bind_hd = NULL;
    Frreport_body_data *p_st_report_body = NULL;
    L7session_sybase *p_st_session = p_st_private->p_st_sess;
    L7_fragment_sybase *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 判断创建request */
    i_ret = __sybase_chk_request(p_st_private, TDS50_MSGTYPE_BUF_NORMAL);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("__sybase_chk_request failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    p_st_req = p_st_private->p_st_req;

    bytebuff_setPosition(p_st_data, p_st_fragment->ui_parsed_index);
    while (bytebuff_remaining(p_st_data) > 0)
    {
        bytebuff_get_char(p_st_data, &u8_token_type);
        switch (u8_token_type)
        {
            /* TDS5.0 token 类型 */
            case TDS50_TOKEN_CAPABILITY:
                i_ret = sybase_parse_capability_token(p_st_data, i_whole_flg
                                                     , FR_CLIENT_IP_PORT
                                                     , p_st_session);
                break;

            case TDS50_TOKEN_CURCLOSE:
                i_ret = sybase_parse_curclose_token(p_st_data, i_whole_flg
                                                    , p_st_session
                                                    , &p_st_req->l_cursor_id
                                                    , p_st_req->arr_cursor_name
                                                    , &p_st_req->i_declare_flg);
                /* 如果解析成功且是独立的，取得该packe对应的statmentstatement */
                if (i_ret == APM_L7_ANALYZE_SUCC
                    && p_st_req->p_st_statement == NULL)
                {
                    p_st_req->i_req_type = TDS50_TOKEN_CURCLOSE;
                    i_ret = __sybase_get_statement(p_st_private, SYBASE_CURSOR);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                    /* 已经上报过了 */
                    if (p_st_req->p_st_resultset->l_id != -1)
                    {
                        p_st_req->i_report_flg = FR_YES;
                    }

                }
                break;

            case TDS50_TOKEN_CURDECLARE:
                i_ret = sybase_parse_curdeclare_token(p_st_data, i_whole_flg
                                                     , p_st_session, &i_options
                                                     , &p_st_req->p_sql
                                                     , p_st_req->arr_cursor_name);
                /* 如果解析成功，创建statement */
                if (i_ret == APM_L7_ANALYZE_SUCC)
                {
                    /*
                    *  The only currently defined bit is 0x02 which indicates
                    *  that the command is parameterized and that
                    *  PARAMFMT/PARAM tokens follow
                    */
                    p_st_req->i_need_params = i_options & 0x01;
                    p_st_req->i_req_type = TDS50_TOKEN_CURDECLARE;
                    i_ret = __sybase_create_statement(p_st_conn, p_st_private);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                }
                break;

            case TDS50_TOKEN_CURDECLARE2:
                i_ret = sybase_parse_curdeclare2_token(p_st_data, i_whole_flg
                                                      , p_st_session, &i_options
                                                      , &p_st_req->p_sql
                                                      , p_st_req->arr_cursor_name);
                /* 如果解析成功，创建statement */
                if (i_ret == APM_L7_ANALYZE_SUCC)
                {
                    /*
                    *  The only currently defined bit is 0x02 which indicates
                    *  that the command is parameterized and that
                    *  PARAMFMT/PARAM tokens follow
                    */
                    p_st_req->i_need_params = i_options & 0x01;
                    p_st_req->i_req_type = TDS50_TOKEN_CURDECLARE2;
                    i_ret = __sybase_create_statement(p_st_conn, p_st_private);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                }
                break;

            case TDS50_TOKEN_CURDECLARE3:
                i_ret = sybase_parse_curdeclare3_token(p_st_data, i_whole_flg
                                                      , p_st_session, &i_options
                                                      , &p_st_req->p_sql
                                                      , p_st_req->arr_cursor_name);
                /* 如果解析成功，创建statement */
                if (i_ret == APM_L7_ANALYZE_SUCC)
                {
                    /*
                    *  The only currently defined bit is 0x02 which indicates
                    *  that the command is parameterized and that
                    *  PARAMFMT/PARAM tokens follow
                    */
                    p_st_req->i_need_params = i_options & 0x01;
                    p_st_req->i_req_type = TDS50_TOKEN_CURDECLARE3;
                    i_ret = __sybase_create_statement(p_st_conn, p_st_private);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                }
                break;

            case TDS50_TOKEN_CURDELETE:
                printf("attention please\n");
                i_ret = sybase_parse_curdelete_token(p_st_data, i_whole_flg
                                                    , p_st_session
                                                    , &p_st_req->l_cursor_id
                                                    , p_st_req->arr_cursor_name);
                //p_st_req->i_report_flg = FR_YES; todo
                p_st_req->i_req_type = TDS50_TOKEN_CURDELETE;
                break;

            case TDS50_TOKEN_CURFETCH:
                i_ret = sybase_parse_curfetch_token(p_st_data, i_whole_flg
                                                   , p_st_session
                                                   , &p_st_req->l_cursor_id
                                                   , p_st_req->arr_cursor_name);
                /* 如果解析成功且是独立的，取得该packe对应的statmentstatement */
                if (i_ret == APM_L7_ANALYZE_SUCC
                    && p_st_req->p_st_statement == NULL)
                {
                    p_st_req->i_req_type = TDS50_TOKEN_CURFETCH;
                    i_ret = __sybase_get_statement(p_st_private, SYBASE_CURSOR);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                }
                break;

            case TDS50_TOKEN_CURINFO:
                i_ret = sybase_parse_curinfo_token(p_st_data, i_whole_flg
                                                  , p_st_session
                                                  , &p_st_req->l_cursor_id
                                                  , p_st_req->arr_cursor_name);
                /* 如果解析成功且是独立的，取得该packe对应的statmentstatement */
                if (i_ret == APM_L7_ANALYZE_SUCC
                    && p_st_req->p_st_statement == NULL)
                {
                    i_ret = __sybase_get_statement(p_st_private, SYBASE_CURSOR);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                }
                break;

            case TDS50_TOKEN_CURINFO2:
                i_ret = sybase_parse_curinfo2_token(p_st_data, i_whole_flg
                                                   , p_st_session
                                                   , &p_st_req->l_cursor_id
                                                   , p_st_req->arr_cursor_name);
                /* 如果解析成功且是独立的，取得该packe对应的statmentstatement */
                if (i_ret == APM_L7_ANALYZE_SUCC
                    && p_st_req->p_st_statement == NULL)
                {
                    i_ret = __sybase_get_statement(p_st_private, SYBASE_CURSOR);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                }
                break;

            case TDS50_TOKEN_CURINFO3:
                i_ret = sybase_parse_curinfo3_token(p_st_data, i_whole_flg
                                                   , p_st_session
                                                   , &p_st_req->l_cursor_id
                                                   , p_st_req->arr_cursor_name);
                /* 如果解析成功且是独立的，取得该packe对应的statmentstatement */
                if (i_ret == APM_L7_ANALYZE_SUCC
                    && p_st_req->p_st_statement == NULL)
                {
                    i_ret = __sybase_get_statement(p_st_private, SYBASE_CURSOR);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                }
                break;

            case TDS50_TOKEN_CUROPEN:
                i_ret = sybase_parse_curopen_token(p_st_data, i_whole_flg
                                                  , p_st_session
                                                  , &p_st_req->l_cursor_id
                                                  , p_st_req->arr_cursor_name
                                                  , &i_options);
                /* 如果解析成功且是独立的，取得该packe对应的statmentstatement */
                if (i_ret == APM_L7_ANALYZE_SUCC
                    && p_st_req->p_st_statement == NULL)
                {
                    /*
                    *  The only currently defined bit is 0x01 which indicates
                    *  that the command is parameterized and that
                    *  PARAMFMT/PARAM tokens follow
                    */
                    //p_st_req->i_need_params = i_options & 0x01; todo
                    p_st_req->i_req_type = TDS50_TOKEN_CUROPEN;
                    i_ret = __sybase_get_statement(p_st_private, SYBASE_CURSOR);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                    p_st_req->p_st_resultset->l_id = 0;
                }
                break;

            case TDS50_TOKEN_CURUPDATE:
                printf("attention please\n");
                i_ret = sybase_parse_curupdate_token(p_st_data, i_whole_flg
                                                    , p_st_session
                                                    , &p_st_req->l_cursor_id
                                                    , p_st_req->arr_cursor_name
                                                    , &p_st_req->p_sql
                                                    , &i_options);
                p_st_req->i_need_params = i_options & 0x01;
                //p_st_req->i_report_flg = FR_YES; todo
                p_st_req->i_req_type = TDS50_TOKEN_CURUPDATE;
                break;

            case TDS50_TOKEN_DBRPC:
                i_ret = sybase_parse_dbrpc_token(p_st_data, i_whole_flg
                                                , p_st_session
                                                , &p_st_req->p_sql
                                                , &i_options);
                /* 如果解析成功，创建statement */
                if (i_ret == APM_L7_ANALYZE_SUCC)
                {
                    /*
                    *  The only currently defined bit is 0x02 which indicates
                    *  that the command is parameterized and that
                    *  PARAMFMT/PARAM tokens follow
                    */
                    p_st_req->i_need_params = i_options & 0x02;
                    p_st_req->i_report_flg = FR_YES;
                    p_st_req->i_req_type = TDS50_TOKEN_DBRPC;
                    i_ret = __sybase_create_statement(p_st_conn, p_st_private);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                }
                break;

            case TDS50_TOKEN_DBRPC2:
                i_ret = sybase_parse_dbrpc2_token(p_st_data, i_whole_flg
                                                 , p_st_session
                                                 , &p_st_req->p_sql
                                                 , &i_options);
                /* 如果解析成功，创建statement */
                if (i_ret == APM_L7_ANALYZE_SUCC)
                {
                    /*
                    *  The only currently defined bit is 0x02 which indicates
                    *  that the command is parameterized and that
                    *  PARAMFMT/PARAM tokens follow
                    */
                    p_st_req->i_need_params = i_options & 0x02;
                    p_st_req->i_report_flg = FR_YES;
                    p_st_req->i_req_type = TDS50_TOKEN_DBRPC2;
                    i_ret = __sybase_create_statement(p_st_conn, p_st_private);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                }
                break;

            case TDS50_TOKEN_DYNAMIC:
                i_ret = sybase_parse_dynamic_token(p_st_data, i_whole_flg
                                                  , p_st_session
                                                  , FR_CLIENT_IP_PORT
                                                  , &i_dynamic_type
                                                  , &i_options
                                                  , p_st_req->arr_id
                                                  , &p_st_req->p_sql);
                if (i_ret == APM_L7_ANALYZE_SUCC)
                {
                    /* This is a request to prepare stmt */
                    /* This a request to prepare and execute stmt immediately */
                    if (i_dynamic_type & 0x01
                        || i_dynamic_type & 0x08)
                    {
                        i_ret = __sybase_create_statement(p_st_conn, p_st_private);
                        if (i_ret != APM_L7_ANALYZE_SUCC)
                        {
                            return APM_L7_ANALYZE_FAIL;
                        }
                        /* add statement to hash with arr_id */
                        i_ret = sybase_add_statement(p_st_private
                                                    , SYBASE_DYNAMIC
                                                    , FRTDS_DIRECT_REQUEST);
                        if (i_ret != APM_L7_ANALYZE_SUCC)
                        {
                            return APM_L7_ANALYZE_FAIL;
                        }
                        if (i_dynamic_type & 0x08)
                        {
                            p_st_req->i_report_flg = FR_YES;
                        }
                    }

                    /* Request to deallocate a prepared statement */
                    if (i_dynamic_type & 0x04)
                    {
                        //todo
                        printf("please attention\n");
                    }

                    /* get statement from hash */
                    if (p_st_req->p_st_statement == NULL)
                    {
                        i_ret = __sybase_get_statement(p_st_private, SYBASE_DYNAMIC);
                        if (i_ret != APM_L7_ANALYZE_SUCC)
                        {
                            return APM_L7_ANALYZE_FAIL;
                        }
                    }

                    /* This is a request to execute a prepared statement */
                    if (i_dynamic_type & 0x02)
                    {
                        /* set report flag */
                        p_st_req->i_report_flg = FR_YES;
                    }

                    /* Send input format description */
                    if (i_dynamic_type & 0x40)
                    {
                        /* set metadata into statement */
                        p_st_req->i_send_metadata = FR_YES;
                    }
                    /* Parameter data stream follows the dynamic command */
                    p_st_req->i_need_params = i_options & 0x01;
                    /* Means has previously sent FRTDS_ROWFMT information */
                    if (i_options & 0x02)
                    {
                        p_st_req->i_get_metadata = FR_YES;
                    }
                }
                break;

            case TDS50_TOKEN_DYNAMIC2:
                i_ret = sybase_parse_dynamic2_token(p_st_data, i_whole_flg
                                                   , p_st_session
                                                   , FR_CLIENT_IP_PORT
                                                   , &i_dynamic_type
                                                   , &i_options
                                                   , p_st_req->arr_id
                                                   , &p_st_req->p_sql);
                if (i_ret == APM_L7_ANALYZE_SUCC)
                {
                    /* This is a request to prepare stmt */
                    /* Request to deallocate a prepared statement */
                    /* This a request to prepare and execute stmt immediately */
                    if (i_dynamic_type & 0x01
                        || i_dynamic_type & 0x04
                        || i_dynamic_type & 0x08)
                    {
                        i_ret = __sybase_create_statement(p_st_conn, p_st_private);
                        if (i_ret != APM_L7_ANALYZE_SUCC)
                        {
                            return APM_L7_ANALYZE_FAIL;
                        }
                        /* add statement to hash with arr_id */
                        i_ret = sybase_add_statement(p_st_private
                                                    , SYBASE_DYNAMIC
                                                    , FRTDS_DIRECT_REQUEST);
                        if (i_ret != APM_L7_ANALYZE_SUCC)
                        {
                            return APM_L7_ANALYZE_FAIL;
                        }
                        if (i_dynamic_type & 0x08)
                        {
                            p_st_req->i_report_flg = FR_YES;
                        }
                    }

                    /* get statement from hash */
                    if (p_st_req->p_st_statement == NULL)
                    {
                        i_ret = __sybase_get_statement(p_st_private, SYBASE_DYNAMIC);
                        if (i_ret != APM_L7_ANALYZE_SUCC)
                        {
                            return APM_L7_ANALYZE_FAIL;
                        }
                    }

                    /* This is a request to execute a prepared statement */
                    if (i_dynamic_type & 0x02)
                    {
                        /* set report flag */
                        p_st_req->i_report_flg = FR_YES;
                    }

                    /* Send input format description */
                    if (i_dynamic_type & 0x40)
                    {
                        /* set metadata into statement */
                        p_st_req->i_send_metadata = FR_YES;
                    }
                    /* Parameter data stream follows the dynamic command */
                    p_st_req->i_need_params = i_options & 0x01;
                    /* Means has previously sent FRTDS_ROWFMT information */
                    if (i_options & 0x02)
                    {
                        p_st_req->i_get_metadata = FR_YES;
                    }
                }
                break;

            case TDS50_TOKEN_ENVCHANGE:
                i_ret = sybase_parse_envchange_token(p_st_data, i_whole_flg
                                                    , p_st_session);
                break;

            case TDS50_TOKEN_KEY:
                i_ret = sybase_parse_key_token(p_st_data, i_whole_flg
                                              , p_st_session
                                              , &p_st_req->st_metadata_bind);
                break;

            case TDS50_TOKEN_LANGUAGE:
                i_ret = sybase_parse_language_token(p_st_data, i_whole_flg
                                                   , p_st_session, &i_options
                                                   , &p_st_req->p_sql);
                /* 如果解析成功，创建statement */
                if (i_ret == APM_L7_ANALYZE_SUCC)
                {
                    /*
                    *  The only currently defined bit is 0x01 which indicates
                    *  that the command is parameterized and that
                    *  PARAMFMT/PARAM tokens follow
                    */
                    p_st_req->i_need_params = i_options & 0x01;
                    p_st_req->i_report_flg = FR_YES;
                    p_st_req->i_req_type = TDS50_TOKEN_LANGUAGE;
                    i_ret = __sybase_create_statement(p_st_conn, p_st_private);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                }
                break;

            case TDS50_TOKEN_LOGOUT:
                i_ret = sybase_parse_logout_token(p_st_data, i_whole_flg);
                p_st_req->i_req_type = TDS50_TOKEN_LOGOUT;
                break;

            case TDS50_TOKEN_MSG:
                i_ret = sybase_parse_msg_token(p_st_data, i_whole_flg
                                              , p_st_session);
                break;

            case TDS50_TOKEN_OPTIONCMD:
                i_ret = sybase_parse_optioncmd_token(p_st_data, i_whole_flg
                                                     , p_st_session);
                break;

            case TDS50_TOKEN_ORDERBY:
                i_ret = sybase_parse_orderby_token(p_st_data, i_whole_flg
                                                   , p_st_session);
                break;

            case TDS50_TOKEN_ORDERBY2:
                i_ret = sybase_parse_orderby2_token(p_st_data, i_whole_flg
                                                    , p_st_session);
                break;

            case TDS50_TOKEN_PARAMFMT:
                /* 同一个packet出现两次param */
                if (frlist_size(&p_st_req->st_metadata_bind))
                {
                    frlist_remove_all(&p_st_req->st_metadata_tmp, frdb_metadata_node_free);
                    i_ret = sybase_parse_paramfmt_token(p_st_data
                                                       , i_whole_flg
                                                       , p_st_session
                                                       , &p_st_req->st_metadata_tmp);
                }
                else
                {
                    i_ret = sybase_parse_paramfmt_token(p_st_data
                                                       , i_whole_flg
                                                       , p_st_session
                                                       , &p_st_req->st_metadata_bind);
                }
                /* 该metadata需要保存到hash */
                if (i_ret == APM_L7_ANALYZE_SUCC
                    && p_st_req->i_send_metadata == FR_YES
                    && p_st_req->p_st_statement)
                {
                    p_st_req->p_st_statement->st_metadata_bind = p_st_req->st_metadata_bind;
                    memset(&p_st_req->st_metadata_bind, 0x0, sizeof(p_st_req->st_metadata_bind));
                    p_st_req->i_send_metadata = FR_NO;
                }
                break;

            case TDS50_TOKEN_PARAMFMT2:
                if (frlist_size(&p_st_req->st_metadata_bind))
                {
                    frlist_remove_all(&p_st_req->st_metadata_tmp, frdb_metadata_node_free);
                    i_ret = sybase_parse_paramfmt2_token(p_st_data
                                                        , i_whole_flg
                                                        , p_st_session
                                                        , &p_st_req->st_metadata_tmp);
                }
                else
                {
                    i_ret = sybase_parse_paramfmt2_token(p_st_data
                                                        , i_whole_flg
                                                        , p_st_session
                                                        , &p_st_req->st_metadata_bind);
                }
                /* 该metadata需要保存到hash */
                if (i_ret == APM_L7_ANALYZE_SUCC
                    && p_st_req->i_send_metadata == FR_YES
                    && p_st_req->p_st_statement)
                {
                    p_st_req->p_st_statement->st_metadata_bind = p_st_req->st_metadata_bind;
                    memset(&p_st_req->st_metadata_bind, 0x0, sizeof(p_st_req->st_metadata_bind));
                    p_st_req->i_send_metadata = FR_NO;
                }
                break;

            case TDS50_TOKEN_PARAMS:
                if (p_st_req->i_get_metadata == FR_YES)
                {
                    i_ret = sybase_parse_params_token(p_st_data, i_whole_flg
                                                     , p_st_session
                                                     , &p_st_req->p_st_statement->st_metadata_bind
                                                     , p_st_req->i_need_params
                                                     , &p_lst_bind_hd);
                }
                else if (frlist_size(&p_st_req->st_metadata_tmp))
                {
                    i_ret = sybase_parse_params_token(p_st_data, i_whole_flg
                                                     , p_st_session
                                                     , &p_st_req->st_metadata_tmp
                                                     , 0
                                                     , NULL);
                }
                else
                {
                    i_ret = sybase_parse_params_token(p_st_data, i_whole_flg
                                                     , p_st_session
                                                     , &p_st_req->st_metadata_bind
                                                     , p_st_req->i_need_params
                                                     , &p_lst_bind_hd);
                }
                if (i_ret == APM_L7_ANALYZE_SUCC && p_lst_bind_hd)
                {
                    p_st_node = frlist_node_create(p_lst_bind_hd);
                    if (p_st_node == NULL)
                    {
                        frdbg("Create node failed\n");
                        frdb_field_bind_free(&p_lst_bind_hd);
                        return APM_L7_ANALYZE_FAIL;
                    }
                    frlist_push(&p_st_req->p_st_resultset->st_bind_list, p_st_node);
                }
                /* 初始化参数 */
                p_st_req->i_need_params = 0;
                p_st_req->i_get_metadata = FR_NO;
                break;

            case TDS50_TOKEN_RPC:
                i_ret = sybase_parse_rpc_token(p_st_data, i_whole_flg
                                              , p_st_session, &p_st_req->p_sql
                                              , &p_lst_bind_hd);
                /* 如果解析成功，创建statement */
                if (i_ret == APM_L7_ANALYZE_SUCC)
                {
                    /*
                    *  The only currently defined bit is 0x02 which indicates
                    *  that the command is parameterized and that
                    *  PARAMFMT/PARAM tokens follow
                    */
                    p_st_req->i_req_type = TDS50_TOKEN_RPC;
                    i_ret = __sybase_create_statement(p_st_conn, p_st_private);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                    if (p_lst_bind_hd)
                    {
                        p_st_node = frlist_node_create(p_lst_bind_hd);
                        if (p_st_node == NULL)
                        {
                            frdbg("Create node failed\n");
                            frdb_field_bind_free(&p_lst_bind_hd);
                            return APM_L7_ANALYZE_FAIL;
                        }
                        frlist_push(&p_st_req->p_st_resultset->st_bind_list, p_st_node);
                    }
                }
                break;

            default:
                i_ret = APM_L7_ANALYZE_FAIL;
                break;
        }

        if (i_ret == APM_L7_ANALYZE_SUCC)
        {
            p_st_fragment->ui_parsed_index = bytebuff_getPosition(p_st_data);
        }
        else if (i_ret == APM_L7_ANALYZE_FAIL)
        {
            if (p_st_session->i_confirmed_endian == FR_NO)
            {
                /* do again */
                if (i_angin_flg == FR_NO )
                {
                    /* 设置成大头 */
                    i_angin_flg = FR_YES;
                    p_st_session->i_lint2_endian = BYTE_BIG_ENDIAN;
                    p_st_session->i_lint4_endian = BYTE_BIG_ENDIAN;
                    p_st_session->i_lflt_type = FRTDS_FLT_IEEE_HI;
                    p_st_session->i_ldate_endian = BYTE_BIG_ENDIAN;
                    p_st_session->i_lnoshort_type = FR_NO;
                    p_st_session->i_lflt4_type = FRTDS_FLT_IEEE_HI;
                    p_st_session->i_ldate4_endian = BYTE_BIG_ENDIAN;
                    /* init request */
                    sybase_int_request(p_st_req);
                    bytebuff_setPosition(p_st_data, 0);
                    p_st_fragment->ui_parsed_index = 0;
                }
                else
                {
                    /* 设置回原来的值 */
                    p_st_session->i_lint2_endian = BYTE_LITTLE_ENDIAN;
                    p_st_session->i_lint4_endian = BYTE_LITTLE_ENDIAN;
                    p_st_session->i_lflt_type = FRTDS_FLT_IEEE_LO;
                    p_st_session->i_ldate_endian = BYTE_LITTLE_ENDIAN;
                    p_st_session->i_lnoshort_type = FR_NO;
                    p_st_session->i_lflt4_type = FRTDS_FLT_IEEE_LO;
                    p_st_session->i_ldate4_endian = BYTE_LITTLE_ENDIAN;
                    return APM_L7_ANALYZE_FAIL;
                }
            }
        }
        else
        {
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* 完整的request packet解析完了 */
    if (i_whole_flg == FR_YES)
    {
        p_st_req->i_need_req_resp = FRTDS_DIRECT_RESPONSE;
        p_st_req->u8_packet_type = TDS50_MSGTYPE_NUL;
        /* 更新数据 */
        if (p_st_req->p_st_resultset)
        {
            frdb_set_resultset_req2(p_st_req->p_st_resultset
                                   , p_st_fragment->ui_total_len
                                   , &(p_st_fragment->st_first_timestamp)
                                   , &(p_st_fragment->st_end_timestamp));
        }
        sybase_init_fragment(p_st_fragment);
        /* 上报数据 */
        if (p_st_req->i_report_flg == FR_YES)
        {
            /* 创建report body */
            p_st_report_body = sybase_new_report_body(p_st_conn, p_st_private->p_st_sess);
            /* 创建report body失败时，不释放做成的request */
            if (p_st_report_body == NULL)
            {
                frdbg("sybase_new_report_body failed!\n");
                return APM_L7_ANALYZE_FAIL;
            }

            /* 上报request数据 */
            i_ret = frdb_report_req2(p_st_conn, p_st_hash_report
                                     , p_st_req->p_st_statement
                                     , p_st_req->p_st_resultset
                                     , &p_st_report_body);
            /* 上报request数据失败时，不释放做成的request */
            if (i_ret != FR_SUCC)
            {
                frdbg("frdb_report_req2 failed!\n");
                frreport_body_free(&p_st_report_body);
                return APM_L7_ANALYZE_SUCC;
            }
            //frdbg("Parse sp_cursorclose %ld success!\n", l_cursor_id);
            return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
        }
        return APM_L7_ANALYZE_SUCC;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}
